/* 单例模式 */

// 单例对象
const Database = (function () {
  // 私有变量 undefined
  let instance;

  // 私有方法和属性
  function connectToDatabase() {
    console.log("连接到数据库...");
  }

  // 公共方法和属性
  return {
    getInstance() {
      // 如果instance不存在...
      if (!instance) {
        console.log("初始化全局唯一实例");

        // 就初始化一个instance
        instance = {
          // 该实例有CRUD方法
          query: function (sql) {
            console.log(`执行查询：${sql}`);
          },

          create(sql) {
            console.log("执行插入");
          },

          retreive(sql) {
            console.log("执行查询");
          },

          update(sql) {
            console.log("执行更新");
          },

          delete(sql) {
            console.log("执行删除");
          },
        };

        // 立刻连接数据库
        connectToDatabase();
      }

      // 将初始化好的实例返回
      return instance;
    },
  };
})();

// 首次获取单例时 会进行初始化
const dbInstance1 = Database.getInstance();

// 以后都返回那个早已初始化好的单例对象
const dbInstance2 = Database.getInstance();
const dbInstance3 = Database.getInstance();
const dbInstance4 = Database.getInstance();
const dbInstance5 = Database.getInstance();

console.log(dbInstance1 === dbInstance5); // 输出 true

dbInstance1.query("SELECT * FROM users");
dbInstance2.query("SELECT * FROM contracts");
dbInstance3.query("SELECT * FROM bus");
dbInstance4.query("SELECT * FROM car");
dbInstance5.query("SELECT * FROM wheel");

// 输出：
// 连接到数据库...
// 执行查询：SELECT * FROM users

/* 
以下是一些可能使用单例模式的常见场景：

日志记录器：在应用程序中使用单例模式来创建一个全局的日志记录器，以便在整个应用程序中共享相同的日志实例。

资源池管理：在需要限制对特定资源的并发访问的情况下，可以使用单例模式来创建一个资源池管理器。该管理器可以确保只有一个实例被创建和使用。

数据缓存：在需要缓存和共享数据的情况下，可以使用单例模式来创建一个全局的数据缓存对象。这样可以减少重复的数据读取和提高应用程序的性能。

配置设置：在需要在整个应用程序中共享配置设置的情况下，可以使用单例模式创建一个配置管理器，以确保只有一个配置实例存在。

数据库连接池：在需要管理数据库连接的情况下，可以使用单例模式来创建一个数据库连接池。这样可以限制创建过多的数据库连接，并提供对连接的统一管理。

消息发布/订阅系统：在事件驱动的系统中，可以使用单例模式创建一个全局的消息发布/订阅系统，以便在不同部分之间进行消息通信。

用户登录管理：在需要管理用户登录状态和权限的情况下，可以使用单例模式来创建一个用户登录管理器，以确保只有一个实例来管理用户登录状态。

这些只是一些常见的使用单例模式的场景，实际上单例模式可以在许多其他情况下使用，以确保只有一个实例被创建和访问。
*/
